source('../settings/settings.R')
source('commonFunctions.R')
inputFileDrive1 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=1, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive2 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=2, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive3 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=3, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive4 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=4, distPrev=30, distNext=30))
drive1 <- read.csv(inputFileDrive1)
drive2 <- read.csv(inputFileDrive2)
drive3 <- read.csv(inputFileDrive3)
drive4 <- read.csv(inputFileDrive4, stringsAsFactors = T)
set.seed(43)
combinedDf <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP, drive3$MeanPP,
drive2$StdPP, drive3$StdPP,
drive2$MeanPP_SegMax, drive3$MeanPP_SegMax,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP_SegMax, drive3$StdPP_SegMax,
drive2$StdPP_Seg0, drive3$StdPP_Seg0,
drive2$MeanPP_AccHigh, drive3$MeanPP_AccHigh,
drive2$X.MeanPP_AccLow, drive3$X.MeanPP_AccLow,
drive2$StdPP_AccHigh, drive3$StdPP_AccHigh,
drive2$StdPP_AccLow, drive3$StdPP_AccLow
)
names(combinedDf) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2", "PP_Dev_3",
"Std_PP_2", "Std_PP_3",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2_Straight", "Std_PP_3_Straight",
"Std_PP_2_Turning", "Std_PP_3_Turning",
"Mean_PP_2_AccHigh", "Mean_PP_3_AccHigh",
"Mean_PP_2_AccLow", "Mean_PP_3_AccLow",
"Std_PP_2_AccHigh", "Std_PP_3_AccHigh",
"Std_PP_2_AccLow", "Std_PP_3_AccLow"
)
combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
combinedDf$ActivityEncoded <- factor(ifelse(combinedDf$Activity == "NO", "1", ifelse(combinedDf$Activity == "C", "2", "3")))
# combinedDf$PP_Dev_2_Turning <- ifelse(combinedDf$PP_Dev_2_Turning > 0, combinedDf$PP_Dev_2_Turning, combinedDf$PP_Dev_2_Straight)
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]
combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE_PRIOR <- list(color='green')
COLOR_FAILURE <- list(color='red')
COLOR_COGNITIVE_ACC <- list(color='rgb(158,202,225)')
COLOR_MOTORIC_ACC <- list(color='rgb(58,200,225)')
bargap <- 6
yAxis <- list(
title = "Arousal ΔPP [ln°C²]",
range=c(-0.2, 0.6)
)
# Apply Otsu algorithm to select threshold
ppDev <- combinedDf$PP_After # PP_Dev
ppDevArray <- matrix(ppDev, nrow = 1,ncol = length(ppDev))
THRESHOLD_MILD = otsu(ppDevArray, range=c(min(ppDev), max(ppDev))) # Expected Threshold > 0.042
print(paste0('Threshold: ', THRESHOLD_MILD))
[1] "Threshold: 0.101235546875"
MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
xAxis = list(
title = "Subject",
ticktext = combinedDf_NoStressor$Subject,
tickvals = seq(1, bargap * nrow(combinedDf_NoStressor), by=bargap),
tickmode = "array"
)
combinedDf_NoStressor$SubjectLevel <- seq(1, bargap * nrow(combinedDf_NoStressor), by=bargap)
fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~SubjectLevel, width=1000) %>%
# add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>%
# add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
# add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>%
# add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>%
add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F)
fig_NoStressor <- fig_NoStressor %>% config(mathjax = 'cdn')
htmltools::tagList(fig_NoStressor)
xAxis = list(
title = "Subject",
ticktext = combinedDf_Cognitive$Subject,
tickvals = seq(1, bargap * nrow(combinedDf_Cognitive), by=bargap),
tickmode = "array"
)
combinedDf_Cognitive$SubjectLevel <- seq(1, bargap * nrow(combinedDf_Cognitive), by=bargap)
fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~SubjectLevel, width=1000) %>%
# add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>%
# add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
# add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>%
# add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>%
add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F)
htmltools::tagList(fig_Cognitive)
xAxis = list(
title = "Subject",
ticktext = combinedDf_Motoric$Subject,
tickvals = seq(1, bargap * nrow(combinedDf_Motoric), by=bargap),
tickmode = "array"
)
combinedDf_Motoric$SubjectLevel <- seq(1, bargap * nrow(combinedDf_Motoric), by=bargap)
fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~SubjectLevel, width=1000) %>%
# add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
# add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>%
# add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
# add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>%
# add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
# add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>%
add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F)
htmltools::tagList(fig_Motoric)
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)
Linear model with all variables
linearModel1 <- lm(PP_After ~
+ PP_Dev_2_Straight
+ PP_Dev_3_Straight
+ PP_Dev_2_Turning
+ PP_Dev_3_Turning
+ Std_PP_2_Straight
+ Std_PP_3_Straight
+ Std_PP_2_Turning
+ Std_PP_3_Turning
+ PP_Prior
+ factor(ActivityEncoded),
data=combinedDf)
# anova(model)
summary(linearModel1)
Call:
lm(formula = PP_After ~ +PP_Dev_2_Straight + PP_Dev_3_Straight +
PP_Dev_2_Turning + PP_Dev_3_Turning + Std_PP_2_Straight +
Std_PP_3_Straight + Std_PP_2_Turning + Std_PP_3_Turning +
PP_Prior + factor(ActivityEncoded), data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.076664 -0.027277 -0.000867 0.021999 0.100001
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.07132 0.08729 -0.817 0.4350
PP_Dev_2_Straight 0.71569 0.36574 1.957 0.0821 .
PP_Dev_3_Straight -0.81109 0.44442 -1.825 0.1013
PP_Dev_2_Turning -0.55309 0.44548 -1.242 0.2458
PP_Dev_3_Turning 0.66117 0.46801 1.413 0.1914
Std_PP_2_Straight 1.41894 1.36691 1.038 0.3263
Std_PP_3_Straight 1.27101 0.71461 1.779 0.1090
Std_PP_2_Turning -1.53955 1.68233 -0.915 0.3840
Std_PP_3_Turning 0.16636 1.14505 0.145 0.8877
PP_Prior 0.70952 0.25103 2.826 0.0198 *
factor(ActivityEncoded)2 0.04926 0.07400 0.666 0.5224
factor(ActivityEncoded)3 0.12239 0.05641 2.170 0.0582 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.0682 on 9 degrees of freedom
Multiple R-squared: 0.9037, Adjusted R-squared: 0.7859
F-statistic: 7.675 on 11 and 9 DF, p-value: 0.002452
plot(linearModel1)




linearModel1 <- lm(PP_After ~
Mean_PP_2_AccHigh
+ Mean_PP_2_AccLow
+ Mean_PP_3_AccHigh
+ Mean_PP_3_AccLow
+ Std_PP_2_AccHigh
+ Std_PP_2_AccLow
+ Std_PP_3_AccHigh
+ Std_PP_3_AccLow
# + PP_Prior
+ factor(ActivityEncoded),
data=combinedDf)
# anova(model)
summary(linearModel1)
Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow +
Mean_PP_3_AccHigh + Mean_PP_3_AccLow + Std_PP_2_AccHigh +
Std_PP_2_AccLow + Std_PP_3_AccHigh + Std_PP_3_AccLow + factor(ActivityEncoded),
data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.110015 -0.048043 0.009167 0.036551 0.082263
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.36297 0.09880 -3.674 0.00429 **
Mean_PP_2_AccHigh 2.14482 0.63161 3.396 0.00682 **
Mean_PP_2_AccLow -1.74610 0.63007 -2.771 0.01974 *
Mean_PP_3_AccHigh 2.99003 0.78293 3.819 0.00338 **
Mean_PP_3_AccLow -2.40638 0.75184 -3.201 0.00948 **
Std_PP_2_AccHigh 5.27168 4.04124 1.304 0.22130
Std_PP_2_AccLow -4.34469 2.79301 -1.556 0.15087
Std_PP_3_AccHigh 0.67278 1.84262 0.365 0.72262
Std_PP_3_AccLow 3.14657 2.14416 1.468 0.17297
factor(ActivityEncoded)2 0.18930 0.05019 3.771 0.00365 **
factor(ActivityEncoded)3 0.13988 0.05308 2.635 0.02494 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.07638 on 10 degrees of freedom
Multiple R-squared: 0.8657, Adjusted R-squared: 0.7315
F-statistic: 6.449 on 10 and 10 DF, p-value: 0.003428
plot(linearModel1)




With Prior
linearModelWPrior <- lm(PP_After ~
Mean_PP_2_AccHigh
+ Mean_PP_2_AccLow
+ Mean_PP_3_AccHigh
+ Mean_PP_3_AccLow
+ Std_PP_2_AccHigh
+ Std_PP_2_AccLow
+ Std_PP_3_AccHigh
+ Std_PP_3_AccLow
+ PP_Prior
+ factor(ActivityEncoded),
data=combinedDf)
# anova(model)
summary(linearModelWPrior)
Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow +
Mean_PP_3_AccHigh + Mean_PP_3_AccLow + Std_PP_2_AccHigh +
Std_PP_2_AccLow + Std_PP_3_AccHigh + Std_PP_3_AccLow + PP_Prior +
factor(ActivityEncoded), data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.067676 -0.021534 -0.007049 0.015917 0.088012
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.26129 0.07583 -3.446 0.00733 **
Mean_PP_2_AccHigh 1.63612 0.46949 3.485 0.00689 **
Mean_PP_2_AccLow -1.35111 0.45858 -2.946 0.01632 *
Mean_PP_3_AccHigh 1.63055 0.68413 2.383 0.04100 *
Mean_PP_3_AccLow -1.46332 0.59910 -2.443 0.03721 *
Std_PP_2_AccHigh 6.65712 2.87230 2.318 0.04566 *
Std_PP_2_AccLow -4.05512 1.96633 -2.062 0.06922 .
Std_PP_3_AccHigh -0.99942 1.38885 -0.720 0.49003
Std_PP_3_AccLow 3.57312 1.51344 2.361 0.04254 *
PP_Prior 0.63520 0.18967 3.349 0.00854 **
factor(ActivityEncoded)2 0.12025 0.04088 2.942 0.01645 *
factor(ActivityEncoded)3 0.15861 0.03775 4.202 0.00230 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.05372 on 9 degrees of freedom
Multiple R-squared: 0.9402, Adjusted R-squared: 0.8672
F-statistic: 12.87 on 11 and 9 DF, p-value: 0.00033
plot(linearModelWPrior)



NaNs producedNaNs produced

linearModel3 <- lm(PP_After ~
Mean_PP_2_AccHigh
+ Mean_PP_2_AccLow
+ Mean_PP_3_AccHigh
+ Mean_PP_3_AccLow
# + PP_Prior
+ factor(ActivityEncoded),
data=combinedDf)
# anova(model)
summary(linearModel3)
Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow +
Mean_PP_3_AccHigh + Mean_PP_3_AccLow + factor(ActivityEncoded),
data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.135285 -0.049920 -0.003805 0.045609 0.123392
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.21802 0.06604 -3.301 0.00525 **
Mean_PP_2_AccHigh 2.11765 0.65809 3.218 0.00620 **
Mean_PP_2_AccLow -1.58805 0.65839 -2.412 0.03016 *
Mean_PP_3_AccHigh 2.97984 0.73529 4.053 0.00119 **
Mean_PP_3_AccLow -2.53203 0.69956 -3.619 0.00279 **
factor(ActivityEncoded)2 0.17285 0.05284 3.271 0.00557 **
factor(ActivityEncoded)3 0.16446 0.04579 3.592 0.00295 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.08212 on 14 degrees of freedom
Multiple R-squared: 0.7828, Adjusted R-squared: 0.6896
F-statistic: 8.407 on 6 and 14 DF, p-value: 0.0005398
plot(linearModel3)




# Export the anova table
library(xtable)
lmCoeffs <- summary(linearModel1)$coefficients
lmAnova <- anova(linearModel1)
print(xtable(lmCoeffs, digits=c(0,5,5,5,5)))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Sat Jul 11 19:08:30 2020
\begin{table}[ht]
\centering
\begin{tabular}{rrrrr}
\hline
& Estimate & Std. Error & t value & Pr($>$$|$t$|$) \\
\hline
(Intercept) & -0.36297 & 0.09880 & -3.67377 & 0.00429 \\
Mean\_PP\_2\_AccHigh & 2.14482 & 0.63161 & 3.39577 & 0.00682 \\
Mean\_PP\_2\_AccLow & -1.74610 & 0.63007 & -2.77127 & 0.01974 \\
Mean\_PP\_3\_AccHigh & 2.99003 & 0.78293 & 3.81901 & 0.00338 \\
Mean\_PP\_3\_AccLow & -2.40638 & 0.75184 & -3.20067 & 0.00948 \\
Std\_PP\_2\_AccHigh & 5.27168 & 4.04124 & 1.30447 & 0.22130 \\
Std\_PP\_2\_AccLow & -4.34469 & 2.79301 & -1.55556 & 0.15087 \\
Std\_PP\_3\_AccHigh & 0.67278 & 1.84262 & 0.36512 & 0.72262 \\
Std\_PP\_3\_AccLow & 3.14657 & 2.14416 & 1.46750 & 0.17297 \\
factor(ActivityEncoded)2 & 0.18930 & 0.05019 & 3.77139 & 0.00365 \\
factor(ActivityEncoded)3 & 0.13988 & 0.05308 & 2.63525 & 0.02494 \\
\hline
\end{tabular}
\end{table}
print(xtable(lmAnova), digits=c(0,5,5,5,5))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Sat Jul 11 19:08:30 2020
\begin{table}[ht]
\centering
\begin{tabular}{lrrrrr}
\hline
& Df & Sum Sq & Mean Sq & F value & Pr($>$F) \\
\hline
Mean\_PP\_2\_AccHigh & 1 & 0.15 & 0.15 & 26.27 & 0.0004 \\
Mean\_PP\_2\_AccLow & 1 & 0.00 & 0.00 & 0.32 & 0.5845 \\
Mean\_PP\_3\_AccHigh & 1 & 0.01 & 0.01 & 1.09 & 0.3207 \\
Mean\_PP\_3\_AccLow & 1 & 0.06 & 0.06 & 11.06 & 0.0077 \\
Std\_PP\_2\_AccHigh & 1 & 0.00 & 0.00 & 0.06 & 0.8116 \\
Std\_PP\_2\_AccLow & 1 & 0.00 & 0.00 & 0.50 & 0.4940 \\
Std\_PP\_3\_AccHigh & 1 & 0.03 & 0.03 & 5.02 & 0.0490 \\
Std\_PP\_3\_AccLow & 1 & 0.02 & 0.02 & 3.14 & 0.1070 \\
factor(ActivityEncoded) & 2 & 0.10 & 0.05 & 8.51 & 0.0069 \\
Residuals & 10 & 0.06 & 0.01 & & \\
\hline
\end{tabular}
\end{table}
ppAfter <- combinedDf$PP_After
ppAfterArray <- matrix(ppAfter, nrow = 1,ncol = length(ppAfter))
thresholdPPAfter <- otsu(ppAfterArray, range=c(min(ppAfter), max(ppAfter))) # Expected Threshold > 0.042
print(paste0('Threshold: ', thresholdPPAfter))
[1] "Threshold: 0.101235546875"
selectedDf <- combinedDf %>% select(
"Subject", "Activity", "PP_After", "PP_Prior",
"Mean_PP_2_AccHigh", "Mean_PP_3_AccHigh",
"Mean_PP_2_AccLow", "Mean_PP_3_AccLow",
"Std_PP_2_AccHigh", "Std_PP_3_AccHigh",
"Std_PP_2_AccLow", "Std_PP_3_AccLow")
selectedDf$Subject <- NULL
selectedDf$Activity_NO <- ifelse(selectedDf$Activity == "NO", 1, 0)
selectedDf$Activity_C <- ifelse(selectedDf$Activity == "C", 1, 0)
selectedDf$Activity_M <- ifelse(selectedDf$Activity == "M", 1, 0)
selectedDf$Activity <- NULL
# selectedDf$PP_Dev_1_Turning <- NULL
# selectedDf$Std_PP_2_Straight <- NULL
# selectedDf$Std_PP_2_Turning <- NULL
# selectedDf$Std_PP_3_Straight <- NULL
# selectedDf$Std_PP_3_Turning <- NULL
#
# # According to Linear model
# selectedDf$PP_Dev_2_Straight <- abs(selectedDf$PP_Dev_2_Straight)
# selectedDf$PP_Dev_3_Straight <- abs(selectedDf$PP_Dev_3_Straight)
# selectedDf$PP_Dev_2_Turning <- abs(selectedDf$PP_Dev_2_Turning)
# selectedDf$PP_Dev_3_Turning <- abs(selectedDf$PP_Dev_3_Turning)
# selectedDf$PP_Prior <- abs(selectedDf$PP_Prior) # NULL
selectedDf$Class <- ifelse(selectedDf$PP_After >= thresholdPPAfter, T, F)
selectedDf$PP_After <- NULL
print(names(selectedDf))
[1] "PP_Prior" "Mean_PP_2_AccHigh" "Mean_PP_3_AccHigh" "Mean_PP_2_AccLow" "Mean_PP_3_AccLow" "Std_PP_2_AccHigh"
[7] "Std_PP_3_AccHigh" "Std_PP_2_AccLow" "Std_PP_3_AccLow" "Activity_NO" "Activity_C" "Activity_M"
[13] "Class"
# library(mefa)
# combinedDf <- rep(combinedDf, 10)
set.seed(43)
n_folds <- 3
params <- param <- list(objective = "binary:logistic",
booster = "gbtree",
eval_metric = "auc",
eta = 0.1,
max_depth = 10,
alpha = 1,
lambda = 0,
gamma = 0.45,
min_child_weight = 0.3,
subsample = 0.5,
colsample_bytree = 1)
# XGBoost Model
xgb_m <- xgb.cv( params = param,
data = as.matrix(selectedDf %>% select(-Class)) ,
label = selectedDf$Class,
nrounds = 100,
verbose = F,
prediction = T,
maximize = F, # Change this value to F will help to run with more itineration
nfold = n_folds,
metrics = c("auc", "error"),
early_stopping_rounds = 50,
stratified = T,
scale_pos_weight = 1)
# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA
Performance Metrics
# Prediction
selectedDf$clsPred <- round(xgb_m$pred)
computePerformanceResults <- function(sdat){
sdat = sdat[complete.cases(sdat),]
acc = sum(sdat[,1] == sdat[,2])/nrow(sdat)
conf_mat = table(sdat)
specif = conf_mat[1,1]/sum(conf_mat[,1])
sensiv = conf_mat[2,2]/sum(conf_mat[,2])
preci = conf_mat[2,2]/sum(conf_mat[2,])
npv = conf_mat[1,1]/sum(conf_mat[1,])
return(c(acc,specif,sensiv,preci,npv))
}
# Get average performance
performance <- computePerformanceResults(selectedDf %>% select(Class, clsPred))
acc <- performance[1]
prec <- performance[4]
recall <- performance[3]
spec <- performance[2]
npv <- performance[5]
f1 <- (2 * recall * prec) / (recall + prec)
auc <- as.numeric(xgb_m$evaluation_log[xgb_m$best_iteration, "test_auc_mean"])
print(paste("Accuracy=", round(acc, 2)))
[1] "Accuracy= 0.71"
print(paste("Precision=", round(prec, 2)))
[1] "Precision= 0.33"
print(paste("Recall=", round(recall, 2)))
[1] "Recall= 1"
print(paste("Specificity=", round(spec, 2)))
[1] "Specificity= 0.67"
print(paste("NPV=", round(npv, 2)))
[1] "NPV= 1"
print(paste("F1=", round(f1, 2)))
[1] "F1= 0.5"
print(paste("AUC=", round(auc, 2)))
[1] "AUC= 0.65"
# Importance
bst <- xgboost( params = param,
data = as.matrix(selectedDf %>% select(-c(Class, clsPred))) ,
label = selectedDf$Class,
nrounds = 100,
verbose = F,
prediction = T,
maximize = F, # Change this value to F will help to run with more itineration
nfold = n_folds,
metrics = c("auc", "error"),
early_stopping_rounds = 50,
stratified = T,
scale_pos_weight = 1)
importanceDf <- xgb.importance(colnames(selectedDf %>% select(-c(Class, clsPred))), model = bst)
print(importanceDf)
library(pROC)
dfROC <- pROC::roc(response = ifelse(selectedDf$Class==T, 1, 0),
predictor = round(xgb_m$pred),
levels=c(0, 1), direction = "<")
# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter
plot(pROC::roc(response = ifelse(selectedDf$Class==T, 1, 0),
predictor = round(xgb_m$pred),
levels=c(0, 1), direction = "<"),
legacy.axes = TRUE,
main="ROC Curve",
lwd=1.5)

Plot feature importance
yAxis <- list(
title = 'Importance',
range=c(0.0, 1.0)
)
xAxis <- list(
title = ''
)
importanceDf$Feature <- factor(importanceDf$Feature, levels = importanceDf[order(-Gain),]$Feature)
fig_Importance <- plot_ly(importanceDf, x = ~Feature, y = ~Gain, type = 'bar', name = 'Gain', width=600) %>%
add_trace(y = ~Cover, name = 'Cover') %>%
add_trace(y = ~Frequency, name = 'Frequency') %>%
layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', title="Feature Importance") %>%
config(.Last.value, mathjax = 'cdn')
htmltools::tagList(fig_Importance)
actualCluster <- data.frame(cbind(as.character(combinedDf$Subject), selectedDf$Class))
names(actualCluster) <- c("Subject", "Class")
actualCluster
# actualCluster[order(Class),]
clusteringDf <- selectedDf %>% select(importanceDf$Feature[1:4])
rownames(clusteringDf) <- paste0(combinedDf$Subject)
fit <- kmeans(clusteringDf, 3)
clusplot(clusteringDf, fit$cluster, color=TRUE, shade=TRUE,
labels=2, lines=0)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQppbnB1dEZpbGVEcml2ZTEgPC0gc3RyX2ludGVycCgiLi4vZGF0YS9wcm9jZXNzZWQvYW5hbHlzaXMvVFQxX0RyaXZlXyR7ZHJpdmV9X1BQXyR7ZGlzdFByZXZ9bV8ke2Rpc3ROZXh0fW0uY3N2IiwgbGlzdChkcml2ZT0xLCBkaXN0UHJldj1ESVNUQU5DRV9QUkVWLCBkaXN0TmV4dD1ESVNUQU5DRV9ORVhUKSkKaW5wdXRGaWxlRHJpdmUyIDwtIHN0cl9pbnRlcnAoIi4uL2RhdGEvcHJvY2Vzc2VkL2FuYWx5c2lzL1RUMV9Ecml2ZV8ke2RyaXZlfV9QUF8ke2Rpc3RQcmV2fW1fJHtkaXN0TmV4dH1tLmNzdiIsIGxpc3QoZHJpdmU9MiwgZGlzdFByZXY9RElTVEFOQ0VfUFJFViwgZGlzdE5leHQ9RElTVEFOQ0VfTkVYVCkpCmlucHV0RmlsZURyaXZlMyA8LSBzdHJfaW50ZXJwKCIuLi9kYXRhL3Byb2Nlc3NlZC9hbmFseXNpcy9UVDFfRHJpdmVfJHtkcml2ZX1fUFBfJHtkaXN0UHJldn1tXyR7ZGlzdE5leHR9bS5jc3YiLCBsaXN0KGRyaXZlPTMsIGRpc3RQcmV2PURJU1RBTkNFX1BSRVYsIGRpc3ROZXh0PURJU1RBTkNFX05FWFQpKQppbnB1dEZpbGVEcml2ZTQgPC0gc3RyX2ludGVycCgiLi4vZGF0YS9wcm9jZXNzZWQvYW5hbHlzaXMvVFQxX0RyaXZlXyR7ZHJpdmV9X1BQXyR7ZGlzdFByZXZ9bV8ke2Rpc3ROZXh0fW0uY3N2IiwgbGlzdChkcml2ZT00LCBkaXN0UHJldj0zMCwgZGlzdE5leHQ9MzApKQoKZHJpdmUxIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMSkKZHJpdmUyIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMikKZHJpdmUzIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMykKCmRyaXZlNCA8LSByZWFkLmNzdihpbnB1dEZpbGVEcml2ZTQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg0MykKY29tYmluZWREZiA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUCwgZHJpdmUzJE1lYW5QUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZ01heCwgZHJpdmUzJE1lYW5QUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWdNYXgsIGRyaXZlMyRTdGRQUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWcwLCBkcml2ZTMkU3RkUFBfU2VnMCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX0FjY0hpZ2gsIGRyaXZlMyRNZWFuUFBfQWNjSGlnaCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkWC5NZWFuUFBfQWNjTG93LCBkcml2ZTMkWC5NZWFuUFBfQWNjTG93LAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9BY2NIaWdoLCBkcml2ZTMkU3RkUFBfQWNjSGlnaCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFBfQWNjTG93LCBkcml2ZTMkU3RkUFBfQWNjTG93CiAgICAgICAgICAgICAgICAgICkKbmFtZXMoY29tYmluZWREZikgPC0gYyhuYW1lcyhkcml2ZTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzFfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yIiwgIlBQX0Rldl8zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yIiwgIlN0ZF9QUF8zIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfU3RyYWlnaHQiLCAiUFBfRGV2XzNfU3RyYWlnaHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfVHVybmluZyIsICJQUF9EZXZfM19UdXJuaW5nIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yX1N0cmFpZ2h0IiwgIlN0ZF9QUF8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yX1R1cm5pbmciLCAiU3RkX1BQXzNfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIk1lYW5fUFBfMl9BY2NIaWdoIiwgIk1lYW5fUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgICAgICAiTWVhbl9QUF8yX0FjY0xvdyIsICJNZWFuX1BQXzNfQWNjTG93IiwKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzJfQWNjSGlnaCIsICJTdGRfUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzJfQWNjTG93IiwgIlN0ZF9QUF8zX0FjY0xvdyIKICAgICAgICAgICAgICAgICAgICAgICApCgpjb21iaW5lZERmJFN1YmplY3QgPC0gcGFzdGUwKCIjIiwgc3RyX3BhZChjb21iaW5lZERmJFN1YmplY3QsIDIsIHBhZD0iMCIpKQpjb21iaW5lZERmJEFjdGl2aXR5RW5jb2RlZCA8LSBmYWN0b3IoaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIiwgIjEiLCBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiQyIsICIyIiwgIjMiKSkpCgojIGNvbWJpbmVkRGYkUFBfRGV2XzJfVHVybmluZyA8LSBpZmVsc2UoY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nID4gMCwgY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nLCBjb21iaW5lZERmJFBQX0Rldl8yX1N0cmFpZ2h0KQpgYGAKCmBgYHtyfQpjb21iaW5lZERmX05vU3RyZXNzb3IgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJOTyIsXQpjb21iaW5lZERmX0NvZ25pdGl2ZSA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIkMiLF0KY29tYmluZWREZl9Nb3RvcmljIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTSIsXQoKY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3QgPC0gYXMuZmFjdG9yKGNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0KQpjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0KQpjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Nb3RvcmljJFN1YmplY3QpCmBgYAoKYGBge3J9CkNPTE9SX05PUk1BTCA8LSBsaXN0KGNvbG9yPSdyZ2IoMTIwLDEyMCwxMjApJykKQ09MT1JfQ09HTklUSVZFIDwtIGxpc3QoY29sb3I9J3JnYigxNTgsMjAyLDIyNSknKQpDT0xPUl9NT1RPUklDIDwtIGxpc3QoY29sb3I9J3JnYig1OCwyMDAsMjI1KScpCkNPTE9SX0ZBSUxVUkVfUFJJT1IgPC0gbGlzdChjb2xvcj0nZ3JlZW4nKQpDT0xPUl9GQUlMVVJFIDwtIGxpc3QoY29sb3I9J3JlZCcpCkNPTE9SX0NPR05JVElWRV9BQ0MgPC0gbGlzdChjb2xvcj0ncmdiKDE1OCwyMDIsMjI1KScpCkNPTE9SX01PVE9SSUNfQUNDIDwtIGxpc3QoY29sb3I9J3JnYig1OCwyMDAsMjI1KScpCgpiYXJnYXAgPC0gNgp5QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gIkFyb3VzYWwgzpRQUCBbbG7CsEPCsl0iLAogIHJhbmdlPWMoLTAuMiwgMC42KQopCgojIEFwcGx5IE90c3UgYWxnb3JpdGhtIHRvIHNlbGVjdCB0aHJlc2hvbGQKcHBEZXYgPC0gY29tYmluZWREZiRQUF9BZnRlciAjIFBQX0RldgpwcERldkFycmF5IDwtIG1hdHJpeChwcERldiwgbnJvdyA9IDEsbmNvbCA9IGxlbmd0aChwcERldikpCiAgClRIUkVTSE9MRF9NSUxEID0gb3RzdShwcERldkFycmF5LCByYW5nZT1jKG1pbihwcERldiksIG1heChwcERldikpKSAjIEV4cGVjdGVkIFRocmVzaG9sZCA+IDAuMDQyCnByaW50KHBhc3RlMCgnVGhyZXNob2xkOiAnLCBUSFJFU0hPTERfTUlMRCkpCgpNQVJLRVJfTElORV9NSUxEID0gbGlzdChjb2xvcj0iYmx1ZSIpCk1BUktFUl9MSU5FX0VYVFJFTUUgPSBsaXN0KGNvbG9yPSJyZWQiKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnhBeGlzID0gbGlzdCgKICB0aXRsZSA9ICJTdWJqZWN0IiwKICB0aWNrdGV4dCA9IGNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0LCAKICB0aWNrdmFscyA9IHNlcSgxLCBiYXJnYXAgKiBucm93KGNvbWJpbmVkRGZfTm9TdHJlc3NvciksIGJ5PWJhcmdhcCksCiAgdGlja21vZGUgPSAiYXJyYXkiCikKY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3RMZXZlbCA8LSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX05vU3RyZXNzb3IpLCBieT1iYXJnYXApCiAgICAgIApmaWdfTm9TdHJlc3NvciA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTm9TdHJlc3NvciwgeCA9IH5TdWJqZWN0TGV2ZWwsIHdpZHRoPTEwMDApICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMV9UdXJuaW5nLCBuYW1lID0gJ05vcm1hbCAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5NZWFuX1BQXzJfQWNjSGlnaCwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIEhBIGluIENEJywgbWFya2VyPUNPTE9SX0NPR05JVElWRV9BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfMl9BY2NMb3csIG5hbWUgPSAnQ29naW5pdGl2ZSAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lIAogIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8zX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAizpRQUCBhZnRlciBIQSBpbiBNRCIsIG1hcmtlcj1DT0xPUl9NT1RPUklDX0FDQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+TWVhbl9QUF8zX0FjY0xvdywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoTG93IEFjY2VsLiknLCBtYXJrZXI9Q09MT1JfQUNDKSAlPiUKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5QUF9BZnRlciwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIHRoZSBjYXRhc3Ryb3BoaWMgZXZlbnQnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PS01LCB4ZW5kPWJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Ob1N0cmVzc29yKSwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9Ik90c3UgVGhyZXNob2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAxIiwgeGVuZD0iIzQxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCB4YXhpcz14QXhpcywgYmFybW9kZSA9ICdncm91cCcsIGJhcmdhcD01LCB0aXRsZT1GKSAKCmZpZ19Ob1N0cmVzc29yIDwtIGZpZ19Ob1N0cmVzc29yICU+JSBjb25maWcobWF0aGpheCA9ICdjZG4nKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Ob1N0cmVzc29yKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnhBeGlzID0gbGlzdCgKICB0aXRsZSA9ICJTdWJqZWN0IiwKICB0aWNrdGV4dCA9IGNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3QsIAogIHRpY2t2YWxzID0gc2VxKDEsIGJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Db2duaXRpdmUpLCBieT1iYXJnYXApLAogIHRpY2ttb2RlID0gImFycmF5IgopCmNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3RMZXZlbCA8LSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX0NvZ25pdGl2ZSksIGJ5PWJhcmdhcCkKCmZpZ19Db2duaXRpdmUgPC0gcGxvdF9seShjb21iaW5lZERmX0NvZ25pdGl2ZSwgeCA9IH5TdWJqZWN0TGV2ZWwsIHdpZHRoPTEwMDApICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMV9UdXJuaW5nLCBuYW1lID0gJ05vcm1hbCAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5NZWFuX1BQXzJfQWNjSGlnaCwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIEhBIGluIENEJywgbWFya2VyPUNPTE9SX0NPR05JVElWRV9BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfMl9BY2NMb3csIG5hbWUgPSAnQ29naW5pdGl2ZSAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lIAogIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8zX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAizpRQUCBhZnRlciBIQSBpbiBNRCIsIG1hcmtlcj1DT0xPUl9NT1RPUklDX0FDQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+TWVhbl9QUF8zX0FjY0xvdywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoTG93IEFjY2VsLiknLCBtYXJrZXI9Q09MT1JfQUNDKSAlPiUKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5QUF9BZnRlciwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIHRoZSBjYXRhc3Ryb3BoaWMgZXZlbnQnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PS01LCB4ZW5kPWJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Ob1N0cmVzc29yKSwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9Ik90c3UgVGhyZXNob2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAxIiwgeGVuZD0iIzQxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCB4YXhpcz14QXhpcywgYmFybW9kZSA9ICdncm91cCcsIGJhcmdhcD01LCB0aXRsZT1GKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Db2duaXRpdmUpCmBgYAoKCgpgYGB7ciwgd2FybmluZz1GfQp4QXhpcyA9IGxpc3QoCiAgdGl0bGUgPSAiU3ViamVjdCIsCiAgdGlja3RleHQgPSBjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCwgCiAgdGlja3ZhbHMgPSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX01vdG9yaWMpLCBieT1iYXJnYXApLAogIHRpY2ttb2RlID0gImFycmF5IgopCmNvbWJpbmVkRGZfTW90b3JpYyRTdWJqZWN0TGV2ZWwgPC0gc2VxKDEsIGJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Nb3RvcmljKSwgYnk9YmFyZ2FwKQoKZmlnX01vdG9yaWMgPC0gcGxvdF9seShjb21iaW5lZERmX01vdG9yaWMsIHggPSB+U3ViamVjdExldmVsLCB3aWR0aD0xMDAwKSAlPiUKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzFfVHVybmluZywgbmFtZSA9ICdOb3JtYWwgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8yX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAnzpRQUCBhZnRlciBIQSBpbiBDRCcsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkVfQUNDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5NZWFuX1BQXzJfQWNjTG93LCBuYW1lID0gJ0NvZ2luaXRpdmUgLSBNZWFuIFBQIChMb3cgQWNjZWwuKScsIG1hcmtlcj1DT0xPUl9BQ0MpICU+JSAKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh0eXBlPSJiYXIiLCB5ID0gfk1lYW5fUFBfM19BY2NIaWdoLCB3aWR0aD0xLjU4LCBuYW1lID0gIs6UUFAgYWZ0ZXIgSEEgaW4gTUQiLCBtYXJrZXI9Q09MT1JfTU9UT1JJQ19BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfM19BY2NMb3csIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lCiAgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9QcmlvciwgbmFtZSA9ICdGYWlsdXJlIC0gUHJpb3IgUFAnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRV9QUklPUikgJT4lCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+UFBfQWZ0ZXIsIHdpZHRoPTEuNTgsIG5hbWUgPSAnzpRQUCBhZnRlciB0aGUgY2F0YXN0cm9waGljIGV2ZW50JywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0tNSwgeGVuZD1iYXJnYXAgKiBucm93KGNvbWJpbmVkRGZfTm9TdHJlc3NvciksIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJPdHN1IFRocmVzaG9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMSIsIHhlbmQ9IiM0MSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgeGF4aXM9eEF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCBiYXJnYXA9NSwgdGl0bGU9RikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfTW90b3JpYykKYGBgCgoKYGBge3J9CmxpYnJhcnkobmxtZSkKY29tYmluZWREZiRTdWJqZWN0ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkU3ViamVjdCkKY29tYmluZWREZiRBY3Rpdml0eSA9IGFzLmZhY3Rvcihjb21iaW5lZERmJEFjdGl2aXR5KQpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9IGlmZWxzZShjb21iaW5lZERmJFBQX0RldiA+IFRIUkVTSE9MRF9NSUxELCAxLCAwKQpgYGAKCiMjIyBFeHRyYWN0IGRhdGEgZm9yIGltcG9ydGFudCBmZWF0dXJlcwpgYGB7cn0KaW1wb3J0YW50RmVhdHVyZXNEZiA8LSBjb21iaW5lZERmICU+JSBzZWxlY3QoU3ViamVjdCwgU3RkX1BQXzMsIFBQX0Rldl8yX1R1cm5pbmcsIEFjdGl2aXR5LCBQUF9EZXYsIFBQX0Rldl9Hcm91cCkKYGBgCgojIExpbmVhciBtb2RlbCB3aXRoIGFsbCB2YXJpYWJsZXMKYGBge3J9CmxpbmVhck1vZGVsMSA8LSBsbShQUF9BZnRlciB+IAogICAgICAgICAgICAgICsgUFBfRGV2XzJfU3RyYWlnaHQKICAgICAgICAgICAgICArIFBQX0Rldl8zX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBQUF9EZXZfMl9UdXJuaW5nCiAgICAgICAgICAgICAgKyBQUF9EZXZfM19UdXJuaW5nCiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9TdHJhaWdodAogICAgICAgICAgICAgICsgU3RkX1BQXzNfU3RyYWlnaHQKICAgICAgICAgICAgICArIFN0ZF9QUF8yX1R1cm5pbmcKICAgICAgICAgICAgICArIFN0ZF9QUF8zX1R1cm5pbmcKICAgICAgICAgICAgICArIFBQX1ByaW9yCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHlFbmNvZGVkKSwgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWwxIDwtIGxtKFBQX0FmdGVyIH4gCiAgICAgICAgICAgICAgICBNZWFuX1BQXzJfQWNjSGlnaAogICAgICAgICAgICAgICsgTWVhbl9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgTWVhbl9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NMb3cKICAgICAgICAgICAgICArIFN0ZF9QUF8yX0FjY0hpZ2gKICAgICAgICAgICAgICArIFN0ZF9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgU3RkX1BQXzNfQWNjSGlnaAogICAgICAgICAgICAgICsgU3RkX1BQXzNfQWNjTG93CiAgICAgICAgICAgICAgIyArIFBQX1ByaW9yCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHlFbmNvZGVkKSwgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgojIyBXaXRoIFByaW9yCmBgYHtyfQpsaW5lYXJNb2RlbFdQcmlvciA8LSBsbShQUF9BZnRlciB+IAogICAgICAgICAgICAgICAgTWVhbl9QUF8yX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfMl9BY2NMb3cKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NIaWdoCiAgICAgICAgICAgICAgKyBNZWFuX1BQXzNfQWNjTG93CiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9BY2NIaWdoCiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9BY2NMb3cKICAgICAgICAgICAgICArIFN0ZF9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIFN0ZF9QUF8zX0FjY0xvdwogICAgICAgICAgICAgICsgUFBfUHJpb3IKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eUVuY29kZWQpLCAKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbFdQcmlvcikKcGxvdChsaW5lYXJNb2RlbFdQcmlvcikKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWwzIDwtIGxtKFBQX0FmdGVyIH4gCiAgICAgICAgICAgICAgICBNZWFuX1BQXzJfQWNjSGlnaAogICAgICAgICAgICAgICsgTWVhbl9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgTWVhbl9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NMb3cKICAgICAgICAgICAgICAjICsgUFBfUHJpb3IKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eUVuY29kZWQpLCAKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbDMpCnBsb3QobGluZWFyTW9kZWwzKQpgYGAKCgpgYGB7cn0KIyBFeHBvcnQgdGhlIGFub3ZhIHRhYmxlCmxpYnJhcnkoeHRhYmxlKQpsbUNvZWZmcyA8LSBzdW1tYXJ5KGxpbmVhck1vZGVsMykkY29lZmZpY2llbnRzCmxtQW5vdmEgPC0gYW5vdmEobGluZWFyTW9kZWwzKQoKcHJpbnQoeHRhYmxlKGxtQ29lZmZzLCBkaWdpdHM9YygwLDUsNSw1LDUpKSkKcHJpbnQoeHRhYmxlKGxtQW5vdmEpLCBkaWdpdHM9YygwLDUsNSw1LDUpKQoKYGBgCgoKYGBge3J9CnBwQWZ0ZXIgPC0gY29tYmluZWREZiRQUF9BZnRlcgpwcEFmdGVyQXJyYXkgPC0gbWF0cml4KHBwQWZ0ZXIsIG5yb3cgPSAxLG5jb2wgPSBsZW5ndGgocHBBZnRlcikpCiAgCnRocmVzaG9sZFBQQWZ0ZXIgPC0gb3RzdShwcEFmdGVyQXJyYXksIHJhbmdlPWMobWluKHBwQWZ0ZXIpLCBtYXgocHBBZnRlcikpKSAjIEV4cGVjdGVkIFRocmVzaG9sZCA+IDAuMDQyCnByaW50KHBhc3RlMCgnVGhyZXNob2xkOiAnLCB0aHJlc2hvbGRQUEFmdGVyKSkKCnNlbGVjdGVkRGYgPC0gY29tYmluZWREZiAlPiUgc2VsZWN0KAogICAgICAgICAgICAgICAgICAiU3ViamVjdCIsICJBY3Rpdml0eSIsICJQUF9BZnRlciIsICJQUF9QcmlvciIsCiAgICAgICAgICAgICAgICAgICJNZWFuX1BQXzJfQWNjSGlnaCIsICJNZWFuX1BQXzNfQWNjSGlnaCIsCiAgICAgICAgICAgICAgICAgICJNZWFuX1BQXzJfQWNjTG93IiwgIk1lYW5fUFBfM19BY2NMb3ciLAogICAgICAgICAgICAgICAgICAiU3RkX1BQXzJfQWNjSGlnaCIsICJTdGRfUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yX0FjY0xvdyIsICJTdGRfUFBfM19BY2NMb3ciKQoKc2VsZWN0ZWREZiRTdWJqZWN0IDwtIE5VTEwKc2VsZWN0ZWREZiRBY3Rpdml0eV9OTyA8LSBpZmVsc2Uoc2VsZWN0ZWREZiRBY3Rpdml0eSA9PSAiTk8iLCAxLCAwKQpzZWxlY3RlZERmJEFjdGl2aXR5X0MgPC0gaWZlbHNlKHNlbGVjdGVkRGYkQWN0aXZpdHkgPT0gIkMiLCAxLCAwKQpzZWxlY3RlZERmJEFjdGl2aXR5X00gPC0gaWZlbHNlKHNlbGVjdGVkRGYkQWN0aXZpdHkgPT0gIk0iLCAxLCAwKQpzZWxlY3RlZERmJEFjdGl2aXR5IDwtIE5VTEwKCiMgc2VsZWN0ZWREZiRQUF9EZXZfMV9UdXJuaW5nIDwtIE5VTEwKIyBzZWxlY3RlZERmJFN0ZF9QUF8yX1N0cmFpZ2h0IDwtIE5VTEwKIyBzZWxlY3RlZERmJFN0ZF9QUF8yX1R1cm5pbmcgPC0gTlVMTAojIHNlbGVjdGVkRGYkU3RkX1BQXzNfU3RyYWlnaHQgPC0gTlVMTAojIHNlbGVjdGVkRGYkU3RkX1BQXzNfVHVybmluZyA8LSBOVUxMCiMgCiMgIyBBY2NvcmRpbmcgdG8gTGluZWFyIG1vZGVsCiMgc2VsZWN0ZWREZiRQUF9EZXZfMl9TdHJhaWdodCA8LSBhYnMoc2VsZWN0ZWREZiRQUF9EZXZfMl9TdHJhaWdodCkKIyBzZWxlY3RlZERmJFBQX0Rldl8zX1N0cmFpZ2h0IDwtIGFicyhzZWxlY3RlZERmJFBQX0Rldl8zX1N0cmFpZ2h0KQojIHNlbGVjdGVkRGYkUFBfRGV2XzJfVHVybmluZyA8LSBhYnMoc2VsZWN0ZWREZiRQUF9EZXZfMl9UdXJuaW5nKQojIHNlbGVjdGVkRGYkUFBfRGV2XzNfVHVybmluZyA8LSBhYnMoc2VsZWN0ZWREZiRQUF9EZXZfM19UdXJuaW5nKQojIHNlbGVjdGVkRGYkUFBfUHJpb3IgPC0gYWJzKHNlbGVjdGVkRGYkUFBfUHJpb3IpICMgTlVMTAoKc2VsZWN0ZWREZiRDbGFzcyA8LSBpZmVsc2Uoc2VsZWN0ZWREZiRQUF9BZnRlciA+PSB0aHJlc2hvbGRQUEFmdGVyLCBULCBGKQpzZWxlY3RlZERmJFBQX0FmdGVyIDwtIE5VTEwKCnByaW50KG5hbWVzKHNlbGVjdGVkRGYpKQpgYGAKCmBgYHtyfQojIGxpYnJhcnkobWVmYSkKIyBjb21iaW5lZERmIDwtIHJlcChjb21iaW5lZERmLCAxMCkgCmBgYAoKYGBge3J9CnNldC5zZWVkKDQzKQpuX2ZvbGRzIDwtIDMKcGFyYW1zIDwtIHBhcmFtIDwtIGxpc3Qob2JqZWN0aXZlICAgICAgID0gImJpbmFyeTpsb2dpc3RpYyIsIAogICAgICAgICAgICAgICBib29zdGVyICAgICAgICAgID0gImdidHJlZSIsCiAgICAgICAgICAgICAgIGV2YWxfbWV0cmljICAgICAgPSAiYXVjIiwKICAgICAgICAgICAgICAgZXRhICAgICAgICAgICAgICA9IDAuMSwKICAgICAgICAgICAgICAgbWF4X2RlcHRoICAgICAgICA9IDEwLAogICAgICAgICAgICAgICBhbHBoYSAgICAgICAgICAgID0gMSwKICAgICAgICAgICAgICAgbGFtYmRhICAgICAgICAgICA9IDAsCiAgICAgICAgICAgICAgIGdhbW1hICAgICAgICAgICAgPSAwLjQ1LAogICAgICAgICAgICAgICBtaW5fY2hpbGRfd2VpZ2h0ID0gMC4zLAogICAgICAgICAgICAgICBzdWJzYW1wbGUgICAgICAgID0gMC41LAogICAgICAgICAgICAgICBjb2xzYW1wbGVfYnl0cmVlID0gMSkKICAgICAgICAgICAKIyBYR0Jvb3N0IE1vZGVsICAgICAgICAgCnhnYl9tIDwtIHhnYi5jdiggICBwYXJhbXMgICAgICAgICAgICAgICA9IHBhcmFtLAogICAgICAgICAgICAgICAgICBkYXRhID0gYXMubWF0cml4KHNlbGVjdGVkRGYgJT4lIHNlbGVjdCgtQ2xhc3MpKSAsCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gIHNlbGVjdGVkRGYkQ2xhc3MsCiAgICAgICAgICAgICAgICAgIG5yb3VuZHMgICAgICAgICAgICAgPSAxMDAsCiAgICAgICAgICAgICAgICAgIHZlcmJvc2UgICAgICAgICAgICAgPSBGLAogICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgbWF4aW1pemUgICAgICAgICAgICA9IEYsICMgQ2hhbmdlIHRoaXMgdmFsdWUgdG8gRiB3aWxsIGhlbHAgdG8gcnVuIHdpdGggbW9yZSBpdGluZXJhdGlvbgogICAgICAgICAgICAgICAgICBuZm9sZCAgICAgICAgICAgICAgID0gbl9mb2xkcywKICAgICAgICAgICAgICAgICAgbWV0cmljcyAgICAgICAgICAgICA9IGMoImF1YyIsICJlcnJvciIpLAogICAgICAgICAgICAgICAgICBlYXJseV9zdG9wcGluZ19yb3VuZHMgPSA1MCwKICAgICAgICAgICAgICAgICAgc3RyYXRpZmllZCAgICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgc2NhbGVfcG9zX3dlaWdodCAgICAgID0gMSkKCiMgeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sInRlc3RfYXVjX21lYW4iXQp4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbixdCgpgYGAKCiMjIFBlcmZvcm1hbmNlIE1ldHJpY3MKYGBge3J9CiMgUHJlZGljdGlvbgpzZWxlY3RlZERmJGNsc1ByZWQgPC0gcm91bmQoeGdiX20kcHJlZCkKCmNvbXB1dGVQZXJmb3JtYW5jZVJlc3VsdHMgPC0gZnVuY3Rpb24oc2RhdCl7CiAgc2RhdCA9IHNkYXRbY29tcGxldGUuY2FzZXMoc2RhdCksXQogIGFjYyA9IHN1bShzZGF0WywxXSA9PSBzZGF0WywyXSkvbnJvdyhzZGF0KQogIGNvbmZfbWF0ID0gdGFibGUoc2RhdCkKICBzcGVjaWYgPSBjb25mX21hdFsxLDFdL3N1bShjb25mX21hdFssMV0pCiAgc2Vuc2l2ID0gY29uZl9tYXRbMiwyXS9zdW0oY29uZl9tYXRbLDJdKQogIHByZWNpID0gIGNvbmZfbWF0WzIsMl0vc3VtKGNvbmZfbWF0WzIsXSkKICBucHYgPSAgICBjb25mX21hdFsxLDFdL3N1bShjb25mX21hdFsxLF0pCiAgcmV0dXJuKGMoYWNjLHNwZWNpZixzZW5zaXYscHJlY2ksbnB2KSkKfQoKIyBHZXQgYXZlcmFnZSBwZXJmb3JtYW5jZQpwZXJmb3JtYW5jZSA8LSBjb21wdXRlUGVyZm9ybWFuY2VSZXN1bHRzKHNlbGVjdGVkRGYgJT4lIHNlbGVjdChDbGFzcywgY2xzUHJlZCkpCmFjYyA8LSBwZXJmb3JtYW5jZVsxXQpwcmVjIDwtIHBlcmZvcm1hbmNlWzRdCnJlY2FsbCA8LSBwZXJmb3JtYW5jZVszXQpzcGVjIDwtIHBlcmZvcm1hbmNlWzJdCm5wdiA8LSBwZXJmb3JtYW5jZVs1XQpmMSA8LSAoMiAqIHJlY2FsbCAqIHByZWMpIC8gKHJlY2FsbCArIHByZWMpCmF1YyA8LSBhcy5udW1lcmljKHhnYl9tJGV2YWx1YXRpb25fbG9nW3hnYl9tJGJlc3RfaXRlcmF0aW9uLCAidGVzdF9hdWNfbWVhbiJdKQoKcHJpbnQocGFzdGUoIkFjY3VyYWN5PSIsIHJvdW5kKGFjYywgMikpKQpwcmludChwYXN0ZSgiUHJlY2lzaW9uPSIsIHJvdW5kKHByZWMsIDIpKSkKcHJpbnQocGFzdGUoIlJlY2FsbD0iLCByb3VuZChyZWNhbGwsIDIpKSkKcHJpbnQocGFzdGUoIlNwZWNpZmljaXR5PSIsIHJvdW5kKHNwZWMsIDIpKSkKcHJpbnQocGFzdGUoIk5QVj0iLCByb3VuZChucHYsIDIpKSkKcHJpbnQocGFzdGUoIkYxPSIsIHJvdW5kKGYxLCAyKSkpCnByaW50KHBhc3RlKCJBVUM9Iiwgcm91bmQoYXVjLCAyKSkpCmBgYAoKYGBge3J9CiMgSW1wb3J0YW5jZQpic3QgPC0geGdib29zdCggICBwYXJhbXMgICAgICAgICAgICAgICA9IHBhcmFtLAogICAgICAgICAgICAgICAgICBkYXRhID0gYXMubWF0cml4KHNlbGVjdGVkRGYgJT4lIHNlbGVjdCgtYyhDbGFzcywgY2xzUHJlZCkpKSAsCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gIHNlbGVjdGVkRGYkQ2xhc3MsCiAgICAgICAgICAgICAgICAgIG5yb3VuZHMgICAgICAgICAgICAgPSAxMDAsCiAgICAgICAgICAgICAgICAgIHZlcmJvc2UgICAgICAgICAgICAgPSBGLAogICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgbWF4aW1pemUgICAgICAgICAgICA9IEYsICMgQ2hhbmdlIHRoaXMgdmFsdWUgdG8gRiB3aWxsIGhlbHAgdG8gcnVuIHdpdGggbW9yZSBpdGluZXJhdGlvbgogICAgICAgICAgICAgICAgICBuZm9sZCAgICAgICAgICAgICAgID0gbl9mb2xkcywKICAgICAgICAgICAgICAgICAgbWV0cmljcyAgICAgICAgICAgICA9IGMoImF1YyIsICJlcnJvciIpLAogICAgICAgICAgICAgICAgICBlYXJseV9zdG9wcGluZ19yb3VuZHMgPSA1MCwKICAgICAgICAgICAgICAgICAgc3RyYXRpZmllZCAgICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgc2NhbGVfcG9zX3dlaWdodCAgICAgID0gMSkKaW1wb3J0YW5jZURmIDwtIHhnYi5pbXBvcnRhbmNlKGNvbG5hbWVzKHNlbGVjdGVkRGYgJT4lIHNlbGVjdCgtYyhDbGFzcywgY2xzUHJlZCkpKSwgbW9kZWwgPSBic3QpCnByaW50KGltcG9ydGFuY2VEZikKYGBgCgpgYGB7cn0KbGlicmFyeShwUk9DKQoKZGZST0MgPC0gcFJPQzo6cm9jKHJlc3BvbnNlID0gaWZlbHNlKHNlbGVjdGVkRGYkQ2xhc3M9PVQsIDEsIDApLAogICAgICAgICAgICAgICBwcmVkaWN0b3IgPSByb3VuZCh4Z2JfbSRwcmVkKSwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSksIGRpcmVjdGlvbiA9ICI8IikKCiMgaXQgPSB3aGljaC5tYXgoeGdiX20kZXZhbHVhdGlvbl9sb2ckdGVzdF9hdWNfbWVhbikKIyBiZXN0Lml0ZXIgPSB4Z2JfbSRldmFsdWF0aW9uX2xvZyRpdGVyW2l0XQojIGJlc3QuaXRlciAKCnBsb3QocFJPQzo6cm9jKHJlc3BvbnNlID0gaWZlbHNlKHNlbGVjdGVkRGYkQ2xhc3M9PVQsIDEsIDApLAogICAgICAgICAgICAgICBwcmVkaWN0b3IgPSByb3VuZCh4Z2JfbSRwcmVkKSwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSksIGRpcmVjdGlvbiA9ICI8IiksIAogICAgIGxlZ2FjeS5heGVzID0gVFJVRSwKICAgICBtYWluPSJST0MgQ3VydmUiLCAKICAgICBsd2Q9MS41KSAKYGBgCgoKIyMjIFBsb3QgZmVhdHVyZSBpbXBvcnRhbmNlCmBgYHtyfQp5QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gJ0ltcG9ydGFuY2UnLAogIHJhbmdlPWMoMC4wLCAxLjApCikKeEF4aXMgPC0gbGlzdCgKICB0aXRsZSA9ICcnCikKCmltcG9ydGFuY2VEZiRGZWF0dXJlIDwtIGZhY3RvcihpbXBvcnRhbmNlRGYkRmVhdHVyZSwgbGV2ZWxzID0gaW1wb3J0YW5jZURmW29yZGVyKC1HYWluKSxdJEZlYXR1cmUpCmZpZ19JbXBvcnRhbmNlIDwtIHBsb3RfbHkoaW1wb3J0YW5jZURmLCB4ID0gfkZlYXR1cmUsIHkgPSB+R2FpbiwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ0dhaW4nLCB3aWR0aD02MDApICU+JQogIGFkZF90cmFjZSh5ID0gfkNvdmVyLCBuYW1lID0gJ0NvdmVyJykgJT4lIAogIGFkZF90cmFjZSh5ID0gfkZyZXF1ZW5jeSwgbmFtZSA9ICdGcmVxdWVuY3knKSAlPiUgCiAgbGF5b3V0KHlheGlzID0geUF4aXMsIHhheGlzPXhBeGlzLCBiYXJtb2RlID0gJ2dyb3VwJywgdGl0bGU9IkZlYXR1cmUgSW1wb3J0YW5jZSIpICU+JSAKICBjb25maWcoLkxhc3QudmFsdWUsIG1hdGhqYXggPSAnY2RuJykKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfSW1wb3J0YW5jZSkKYGBgCgpgYGB7cn0KYWN0dWFsQ2x1c3RlciA8LSBkYXRhLmZyYW1lKGNiaW5kKGFzLmNoYXJhY3Rlcihjb21iaW5lZERmJFN1YmplY3QpLCBzZWxlY3RlZERmJENsYXNzKSkKbmFtZXMoYWN0dWFsQ2x1c3RlcikgPC0gYygiU3ViamVjdCIsICJDbGFzcyIpCmFjdHVhbENsdXN0ZXIKIyBhY3R1YWxDbHVzdGVyW29yZGVyKENsYXNzKSxdCmBgYAoKYGBge3J9CmNsdXN0ZXJpbmdEZiA8LSBzZWxlY3RlZERmICU+JSBzZWxlY3QoaW1wb3J0YW5jZURmJEZlYXR1cmVbMTo0XSkKcm93bmFtZXMoY2x1c3RlcmluZ0RmKSA8LSBwYXN0ZTAoY29tYmluZWREZiRTdWJqZWN0KQpmaXQgPC0ga21lYW5zKGNsdXN0ZXJpbmdEZiwgMykKY2x1c3Bsb3QoY2x1c3RlcmluZ0RmLCBmaXQkY2x1c3RlciwgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwKICAgbGFiZWxzPTIsIGxpbmVzPTApCmBgYAoK